package com.zxy.supplier_system.server.entity

import jakarta.persistence.*
import org.hibernate.annotations.DynamicUpdate
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.math.BigDecimal
import java.time.OffsetDateTime

@Entity
@EntityListeners(AuditingEntityListener::class)
@DynamicUpdate
@Table(
    indexes = [
        Index(name = "number_unique", columnList = "number", unique = true)
    ]
)
class Procurement {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id = 0

    @Column(nullable = false)
    lateinit var number: String

    @CreatedBy
    @ManyToOne(optional = false)
    @JoinColumn
    lateinit var createdBy: Employee

    lateinit var createdDateTime: OffsetDateTime

    var submittedDateTime: OffsetDateTime? = null

    @OneToOne(mappedBy = "procurement")
    var procurementReceipt: ProcurementReceipt? = null

    @OneToMany(mappedBy = "procurement", cascade = [CascadeType.ALL], orphanRemoval = true)
    @OrderBy(value = "sequence asc")
    var items: MutableList<ProcurementItem> = mutableListOf()

    @ManyToOne(optional = false)
    @JoinColumn
    lateinit var supplier: ProcurementSupplier

    @OneToOne(mappedBy = "procurement")
    @JoinColumn
    var receipt: ProcurementReceipt? = null

    enum class Status {
        WAIT_SUBMIT,
        SUBMITTED,
        RECEIPT,
    }

    @get:Transient
    val status: Status
        get() {
            return if (submittedDateTime == null) {
                Status.WAIT_SUBMIT
            } else if (procurementReceipt == null) {
                Status.SUBMITTED
            } else {
                Status.RECEIPT
            }
        }

    var note: String? = null

}

val List<ProcurementItem>.nextSequence: Int
    get() = this.maxOfOrNull {
        it.sequence
    }?.plus(1) ?: 0

val List<ProcurementItem>.totalPurchasePrice: BigDecimal
    get() = this.map { item ->
        item.purchasePrice * BigDecimal.valueOf(
            item.amount.toLong() * (item.unit?.practicalMultiple ?: 1)
        )
    }.sumOf { it }